#ifndef US_DATA_H_
#define US_DATA_H_

// Default data boundaries
#define US_DATA_YAW_MIN 0
#define US_DATA_YAW_MAX 360
#define US_DATA_PITCH_MIN -90
#define US_DATA_PITCH_MAX 90
#define US_DATA_ROLL_MIN -180
#define US_DATA_ROLL_MAX 180
#define US_DATA_HEADING_MIN 0
#define US_DATA_HEADING_MAX 360
#define US_DATA_LATITUDE_MIN -180.0
#define US_DATA_LATITUDE_MAX 180.0
#define US_DATA_LONGITUDE_MIN -180.0
#define US_DATA_LONGITUDE_MAX 180.0
#define US_DATA_ALTITUDE_MIN -99.99f
#define US_DATA_ALTITUDE_MAX 9999.99f
#define US_DATA_AIRSPEED_MIN -99.99f
#define US_DATA_AIRSPEED_MAX 999.99f
#define US_DATA_GROUNDSPEED_MIN -99.99f
#define US_DATA_GROUNDSPEED_MAX 999.99f

#include "AbstractData.h"
/*
* class USData
* 
* Represents the data for sentence to be sent from USTAV Server to USTAV Router.
*
*  Created on: 17.1.2012.
*      Author: Hetcheem
*
* DATA                 min         max  bytes  + comma    unit  data type
* -----------------------------------------------------------------------
* Yaw                    0         360      3        4     deg        int
* Pitch                -90          90      3        4     deg        int
* Roll                -180         180      4        5     deg        int
* Heading                0         360      3        4     deg        int
* Latitude     -180.000000  180.000000     11       12     deg     double   (precision 1.11 cm)
* Longitude    -180.000000  180.000000     11       12     deg     double
* Altitude          -99.99     9999.99      7        8       m      float
* Airspeed          -99.99      999.99      6        7    km/h      float
* Ground Speed      -99.99      999.99      6        7    km/h      float
* -----------------------------------------------------------------------
* TOTAL                                    54       63
* BASE + DATA                                       81
*/
class USData : public AbstractData
{
private:
    // Data members
    int m_yaw;
    int m_pitch;
    int m_roll;
    int m_heading;
    double m_latitude;
    double m_longitude;
    float m_altitude;
    float m_airspeed;
    float m_groundSpeed;

    // Data handling
    int SerializeSentence(std::stringstream& stream, const bool& isSending)
    {
        // Call base class serialization
        AbstractData::SerializeSentence(stream, isSending);

        if (isSending)
        {
            // Send data to stream
            stream << m_yaw << ',';
            stream << m_pitch << ',';
            stream << m_roll << ',';
            stream << m_heading << ',';
            stream << std::setprecision(6) << m_latitude << ',';
            stream << std::setprecision(6) << m_longitude << ',';
            stream << std::setprecision(2) << m_altitude << ',';
            stream << std::setprecision(2) << m_airspeed << ',';
            stream << std::setprecision(2) << m_groundSpeed;
        }
        else
        {
            char comma;
            int yaw, pitch, roll, heading;
            double latitude, longitude;
            float altitude, airspeed, groundSpeed;

            // Recieve data from stream
            stream >> yaw >> comma;
            stream >> pitch >> comma;
            stream >> roll >> comma;
            stream >> heading >> comma;
            stream >> latitude >> comma;
            stream >> longitude >> comma;
            stream >> altitude >> comma;
            stream >> airspeed >> comma;
            stream >> groundSpeed;

            // Set the values
            SetYaw(yaw);
            SetPitch(pitch);
            SetRoll(roll);
            SetHeading(heading);
            SetLatitude(latitude);
            SetLongitude(longitude);
            SetAltitude(altitude);
            SetAirspeed(airspeed);
            SetGroundSpeed(groundSpeed);
        }

        return 0;
    }

public:
    // Constructor
    USData(): AbstractData("USDAT"),
        m_yaw(0), m_pitch(0), m_roll(0),
        m_heading(0), m_latitude(0), m_longitude(0),
        m_altitude(0), m_airspeed(0), m_groundSpeed(0)
    {}

    // Get
    inline const int& GetYaw() { return m_yaw; }
    inline const int& GetPitch() { return m_pitch; }
    inline const int& GetRoll() { return m_roll; }
    inline const int& GetHeading() { return m_heading; }
    inline const double& GetLatitude() { return m_latitude; }
    inline const double& GetLongitude() { return m_longitude; }
    inline const float& GetAltitude() { return m_altitude; }
    inline const float& GetAirspeed() { return m_airspeed; }
    inline const float& GetGroundSpeed() { return m_groundSpeed;}

    // Set
    int USData::SetYaw(const int& value)
    {
        if (value > US_DATA_YAW_MAX)
        {
            m_yaw = US_DATA_YAW_MAX;
            return 666;
        }
        else if (value < US_DATA_YAW_MIN)
        {
            m_yaw = US_DATA_YAW_MIN;
            return -666;
        }

        m_yaw = value;
        return 0;
    }

    int USData::SetPitch(const int& value)
    {
        if (value > US_DATA_PITCH_MAX)
        {
            m_pitch = US_DATA_PITCH_MAX;
            return 666;
        }
        else if (value < US_DATA_PITCH_MIN)
        {
            m_pitch = US_DATA_PITCH_MIN;
            return -666;
        }

        m_pitch = value;
        return 0;
    }

    int USData::SetRoll(const int& value)
    {
        if (value > US_DATA_ROLL_MAX)
        {
            m_roll = US_DATA_ROLL_MAX;
            return 666;
        }
        else if (value < US_DATA_ROLL_MIN)
        {
            m_roll = US_DATA_ROLL_MIN;
            return -666;
        }

        m_roll = value;
        return 0;
    }

    int USData::SetHeading(const int& value)
    {
        if (value > US_DATA_HEADING_MAX)
        {
            m_heading = US_DATA_HEADING_MAX;
            return 666;
        }
        else if (value < US_DATA_HEADING_MIN)
        {
            m_heading = US_DATA_HEADING_MIN;
            return -666;
        }

        m_heading = value;
        return 0;
    }

    int USData::SetLatitude(const double& value)
    {
        if (value > US_DATA_LATITUDE_MAX)
        {
            m_latitude = US_DATA_LATITUDE_MAX;
            return 666;
        }
        else if (value < US_DATA_LATITUDE_MIN)
        {
            m_latitude = US_DATA_LATITUDE_MIN;
            return -666;
        }

        m_latitude = value;
        return 0;
    }

    int USData::SetLongitude(const double& value)
    {
        if (value > US_DATA_LONGITUDE_MAX)
        {
            m_longitude = US_DATA_LONGITUDE_MAX;
            return 666;
        }
        else if (value < US_DATA_LONGITUDE_MIN)
        {
            m_longitude = US_DATA_LONGITUDE_MIN;
            return -666;
        }

        m_longitude = value;
        return 0;
    }

    int USData::SetAltitude(const float& value)
    {
        if (value > US_DATA_ALTITUDE_MAX)
        {
            m_altitude = US_DATA_ALTITUDE_MAX;
            return 666;
        }
        else if (value < US_DATA_ALTITUDE_MIN)
        {
            m_altitude = US_DATA_ALTITUDE_MIN;
            return -666;
        }

        m_altitude = value;
        return 0;
    }

    int USData::SetAirspeed(const float& value)
    {
        if (value > US_DATA_AIRSPEED_MAX)
        {
            m_airspeed = US_DATA_AIRSPEED_MAX;
            return 666;
        }
        else if (value < US_DATA_AIRSPEED_MIN)
        {
            m_airspeed = US_DATA_AIRSPEED_MIN;
            return -666;
        }

        m_airspeed = value;
        return 0;
    }

    int USData::SetGroundSpeed(const float& value)
    {
        if (value > US_DATA_GROUNDSPEED_MAX)
        {
            m_groundSpeed = US_DATA_GROUNDSPEED_MAX;
            return 666;
        }
        else if (value < US_DATA_GROUNDSPEED_MIN)
        {
            m_groundSpeed = US_DATA_GROUNDSPEED_MIN;
            return -666;
        }

        m_groundSpeed = value;
        return 0;
    }
};

#endif /* US_DATA_H_ */